package org.rqb.listener;

import com.github.kwhat.jnativehook.keyboard.NativeKeyEvent;
import com.github.kwhat.jnativehook.keyboard.NativeKeyListener;
import com.github.kwhat.jnativehook.mouse.NativeMouseEvent;
import com.github.kwhat.jnativehook.mouse.NativeMouseInputListener;
import com.github.kwhat.jnativehook.mouse.NativeMouseWheelEvent;
import com.github.kwhat.jnativehook.mouse.NativeMouseWheelListener;
import lombok.extern.slf4j.Slf4j;
import org.rqb.entry.MyEvent;
import org.rqb.panel.RepeatPanel;

import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

@Slf4j
public class RepeatMouseAndKeyRepeatListener implements NativeMouseInputListener, NativeMouseWheelListener, NativeKeyListener {

    private final RepeatPanel repeatPanel;
    private List<MyEvent> eventList = new ArrayList<>();
    private HashSet<String> keyStateSet = new HashSet<>();

    private long currentTime;

    public RepeatMouseAndKeyRepeatListener(RepeatPanel repeatPanel) {
        this.repeatPanel = repeatPanel;
    }

    @Override
    public void nativeKeyPressed(NativeKeyEvent e) {
        handleKeyEvent(e, MyEvent.EventType.KEYDOWN);
    }

    @Override
    public void nativeKeyReleased(NativeKeyEvent e) {
        handleKeyEvent(e, MyEvent.EventType.KEYUP);
    }

    /**
     * 处理键盘被按下的事件
     * @param e
     * @param eventType
     */
    private void handleKeyEvent(NativeKeyEvent e, MyEvent.EventType eventType) {
        // 获取对应的robot键
        int keyCode = convertToRobotKeyCode(e.getKeyCode());
        // 保存ctrl状态 保存shift状态
        if (saveCtrlState(e, eventType) | saveShiftState(e, eventType)) {
            eventList.add(new MyEvent(keyCode, eventType, getTimeStamp(System.currentTimeMillis())));
            return;
        }


        if (getCtrlState() && keyCode == KeyEvent.VK_E ){ //表示用户按下了ctrl+E
            //添加事件将ctrl 释放
            eventList.add(new MyEvent(KeyEvent.VK_CONTROL, MyEvent.EventType.KEYUP, 0));
            return;
        }
        eventList.add(new MyEvent(keyCode, eventType, getTimeStamp(System.currentTimeMillis())));
    }


    /**
     * 存储shift的状态
     * @param e
     * @param eventType
     * @return true表示是shift
     */
    private boolean saveShiftState(NativeKeyEvent e, MyEvent.EventType eventType) {
        int keyCode = e.getKeyCode();
        // 判断是否是左/右 Shift 键
        if (keyCode == NativeKeyEvent.VC_SHIFT) {
            if (eventType == MyEvent.EventType.KEYDOWN) {
                keyStateSet.add("shift");
            } else {
                keyStateSet.remove("shift");
            }
            return true;
        }
        return false;
    }

    /**
     * 存储ctrl的状态
     * @param e
     * @param eventType
     * @return true表示是ctrl
     */
    private boolean saveCtrlState(NativeKeyEvent e, MyEvent.EventType eventType) {
        int keyCode = e.getKeyCode();
        // 判断是否是左/右 Control 键
        if (keyCode == NativeKeyEvent.VC_CONTROL) {
            if (eventType == MyEvent.EventType.KEYDOWN) {
                keyStateSet.add("ctrl");
            } else {
                keyStateSet.remove("ctrl");
            }
            return true;
        }
        return false;
    }

    /**
     * 查询ctrl是否被按下
     * @return true表示被按下
     */
    private boolean getCtrlState(){
        if (keyStateSet.contains("ctrl")) {
            return true;
        }
        return false;
    }

    /**
     * 查询shift是否被按下
     * @return true表示被按下
     */
    private boolean getShiftState(){
        if (keyStateSet.contains("shift")) {
            return true;
        }
        return false;
    }


    private int convertToRobotKeyCode(int nativeKeyCode) {
        // 将 NativeKeyEvent 的按键码转换为 Robot 可用的 KeyEvent 按键码
        switch (nativeKeyCode) {
            case NativeKeyEvent.VC_A: return KeyEvent.VK_A;
            case NativeKeyEvent.VC_B: return KeyEvent.VK_B;
            case NativeKeyEvent.VC_C: return KeyEvent.VK_C;
            case NativeKeyEvent.VC_D: return KeyEvent.VK_D;
            case NativeKeyEvent.VC_E: return KeyEvent.VK_E;
            case NativeKeyEvent.VC_F: return KeyEvent.VK_F;
            case NativeKeyEvent.VC_G: return KeyEvent.VK_G;
            case NativeKeyEvent.VC_H: return KeyEvent.VK_H;
            case NativeKeyEvent.VC_I: return KeyEvent.VK_I;
            case NativeKeyEvent.VC_J: return KeyEvent.VK_J;
            case NativeKeyEvent.VC_K: return KeyEvent.VK_K;
            case NativeKeyEvent.VC_L: return KeyEvent.VK_L;
            case NativeKeyEvent.VC_M: return KeyEvent.VK_M;
            case NativeKeyEvent.VC_N: return KeyEvent.VK_N;
            case NativeKeyEvent.VC_O: return KeyEvent.VK_O;
            case NativeKeyEvent.VC_P: return KeyEvent.VK_P;
            case NativeKeyEvent.VC_Q: return KeyEvent.VK_Q;
            case NativeKeyEvent.VC_R: return KeyEvent.VK_R;
            case NativeKeyEvent.VC_S: return KeyEvent.VK_S;
            case NativeKeyEvent.VC_T: return KeyEvent.VK_T;
            case NativeKeyEvent.VC_U: return KeyEvent.VK_U;
            case NativeKeyEvent.VC_V: return KeyEvent.VK_V;
            case NativeKeyEvent.VC_W: return KeyEvent.VK_W;
            case NativeKeyEvent.VC_X: return KeyEvent.VK_X;
            case NativeKeyEvent.VC_Y: return KeyEvent.VK_Y;
            case NativeKeyEvent.VC_Z: return KeyEvent.VK_Z;

            case NativeKeyEvent.VC_0: return KeyEvent.VK_0;
            case NativeKeyEvent.VC_1: return KeyEvent.VK_1;
            case NativeKeyEvent.VC_2: return KeyEvent.VK_2;
            case NativeKeyEvent.VC_3: return KeyEvent.VK_3;
            case NativeKeyEvent.VC_4: return KeyEvent.VK_4;
            case NativeKeyEvent.VC_5: return KeyEvent.VK_5;
            case NativeKeyEvent.VC_6: return KeyEvent.VK_6;
            case NativeKeyEvent.VC_7: return KeyEvent.VK_7;
            case NativeKeyEvent.VC_8: return KeyEvent.VK_8;
            case NativeKeyEvent.VC_9: return KeyEvent.VK_9;


            // 小键盘上的数字键映射为 KeyEvent 中的相应常量
            case 110: return KeyEvent.VK_NUMPAD0;
            case 111: return KeyEvent.VK_NUMPAD1;
            case 112: return KeyEvent.VK_NUMPAD2;
            case 113: return KeyEvent.VK_NUMPAD3;
            case 114: return KeyEvent.VK_NUMPAD4;
            case 115: return KeyEvent.VK_NUMPAD5;
            case 116: return KeyEvent.VK_NUMPAD6;
            case 117: return KeyEvent.VK_NUMPAD7;
            case 118: return KeyEvent.VK_NUMPAD8;
            case 119: return KeyEvent.VK_NUMPAD9;

            //处理键盘上下左右
            case NativeKeyEvent.VC_LEFT: return KeyEvent.VK_LEFT;    // 对应键值37
            case NativeKeyEvent.VC_UP: return KeyEvent.VK_UP;        // 对应键值38
            case NativeKeyEvent.VC_RIGHT: return KeyEvent.VK_RIGHT;  // 对应键值39
            case NativeKeyEvent.VC_DOWN: return KeyEvent.VK_DOWN;     // 对应键值40


            // 处理功能键、控制键等特殊按键
            case NativeKeyEvent.VC_ENTER: return KeyEvent.VK_ENTER;
            case NativeKeyEvent.VC_BACKSPACE: return KeyEvent.VK_BACK_SPACE;
            case NativeKeyEvent.VC_TAB: return KeyEvent.VK_TAB;
            case NativeKeyEvent.VC_SHIFT: return KeyEvent.VK_SHIFT;
            case NativeKeyEvent.VC_CONTROL: return KeyEvent.VK_CONTROL;
            case NativeKeyEvent.VC_ALT: return KeyEvent.VK_ALT;
            case NativeKeyEvent.VC_SPACE: return KeyEvent.VK_SPACE;
            case NativeKeyEvent.VC_CAPS_LOCK: return KeyEvent.VK_CAPS_LOCK;
            case NativeKeyEvent.VC_ESCAPE: return KeyEvent.VK_ESCAPE;
            case NativeKeyEvent.VC_F1: return KeyEvent.VK_F1;
            case NativeKeyEvent.VC_F2: return KeyEvent.VK_F2;
            case NativeKeyEvent.VC_F3: return KeyEvent.VK_F3;
            case NativeKeyEvent.VC_F4: return KeyEvent.VK_F4;
            case NativeKeyEvent.VC_F5: return KeyEvent.VK_F5;
            case NativeKeyEvent.VC_F6: return KeyEvent.VK_F6;
            case NativeKeyEvent.VC_F7: return KeyEvent.VK_F7;
            case NativeKeyEvent.VC_F8: return KeyEvent.VK_F8;
            case NativeKeyEvent.VC_F9: return KeyEvent.VK_F9;
            case NativeKeyEvent.VC_F10: return KeyEvent.VK_F10;
            case NativeKeyEvent.VC_F11: return KeyEvent.VK_F11;
            case NativeKeyEvent.VC_F12: return KeyEvent.VK_F12;

            default: return KeyEvent.VK_UNDEFINED; // 处理未定义的按键
        }
    }

    @Override
    public void nativeMouseClicked(NativeMouseEvent e) {
        log.info("鼠标点击: {} 次，坐标: ({}, {})", e.getClickCount(), e.getX(), e.getY());
    }

    @Override
    public void nativeMousePressed(NativeMouseEvent e) {
        log.info("鼠标按下: 按钮 {}，坐标: ({}, {})", e.getButton(), e.getX(), e.getY());
        eventList.add(new MyEvent(e.getX(), e.getY(), e.getButton() == NativeMouseEvent.BUTTON1 ? MyEvent.EventType.LEFT_MOUSE_DOWN : MyEvent.EventType.RIGHT_MOUSE_DOWN, getTimeStamp(System.currentTimeMillis())));
    }

    @Override
    public void nativeMouseReleased(NativeMouseEvent e) {
        log.info("鼠标释放: 按钮 {}，坐标: ({}, {})", e.getButton(), e.getX(), e.getY());
        eventList.add(new MyEvent(e.getX(), e.getY(), e.getButton() == NativeMouseEvent.BUTTON1 ? MyEvent.EventType.LEFT_MOUSE_UP : MyEvent.EventType.RIGHT_MOUSE_UP, getTimeStamp(System.currentTimeMillis())));
    }

    @Override
    public void nativeMouseMoved(NativeMouseEvent e) {
        log.info("鼠标移动: 坐标 ({}, {})", e.getX(), e.getY());
        eventList.add(new MyEvent(e.getX(), e.getY(), MyEvent.EventType.MOUSE_MOVE, getTimeStamp(System.currentTimeMillis())));
    }

    @Override
    public void nativeMouseDragged(NativeMouseEvent e) {
        log.info("鼠标拖动: 坐标 ({}, {})", e.getX(), e.getY());
    }

    @Override
    public void nativeMouseWheelMoved(NativeMouseWheelEvent e) {
        log.info("鼠标滚轮滚动: {} 单位", e.getWheelRotation());
        eventList.add(new MyEvent(e.getX(), e.getY(), e.getWheelRotation() > 0 ? MyEvent.EventType.MOUSE_WHEEL_DOWN : MyEvent.EventType.MOUSE_WHEEL_UP, getTimeStamp(System.currentTimeMillis())));
    }

    // 获取两次操作之间的间隔
    private long getTimeStamp(long now) {
        long timeStamp = now - this.currentTime;
        this.currentTime = now;
        return timeStamp;
    }

    public List<MyEvent> getEventList() {
        return eventList;
    }

    public void clearEvent(long currentTime) {
        this.currentTime = currentTime;
        eventList.clear();
    }
}
